#include "HiranipraShared.h"

#ifndef _SHARED_MATH_UTILITY_H_
#define _SHARED_MATH_UTILITY_H_

#define MAX( a, b ) ( a > b ? a : b )
#define MIN( a, b ) ( a < b ? a : b )

#define PI (float)(3.14159265358979)
#define PI_2 (float)(3.14159265358979 / 2.0)

#define DEG2RAD(a)	( PI  / 180 * (a) )
#define RAD2DEG(a)	( 180 / PI  * (a) )

namespace Hiranipra {
	namespace Math {

		// Fuzzy compare
		#define EPSILON 0.00001
		#define EQUAL( a, b ) ( fabs( (a - b) / b ) <= EPSILON )

		// INV( r, p ) : r = 1 / p
		#define INV( r, p )	{						\
			int _i = 2 * 0x3F800000 - *(int*)&(p);	\
			r = *(float *)&_i;						\
			r = r * (2.0f - (p) * r);				\
		}

		// EXP( e, p ) : e = exp(p)
		#define EXP( e, p ) {							\
			int _i;										\
			e = -1.44269504f * (float)0x00800000 * (p);	\
			_i = (int)e + 0x3F800000;					\
			e = *(float *)&_i;							\
		}

		FORCE_INLINE void FloatToInt( float f, int *dest )
		{
			__asm
			{
				fld f
				mov edx, dest
				frndint
				fistp dword ptr [edx]
			}
		}

		// 0x5f3759df = original, 0x5f375a86 = from paper
		#define SQRT_MAGIC_CONSTANT 0x5f3759df

		FORCE_INLINE float SQRT( const float number )
		{
#ifndef FAST_SQRT
			return sqrt( number );
#else
			float half = number * 0.5f;
			int i = *( int* )&number;
			i = SQRT_MAGIC_CONSTANT - ( i >> 1 );
			float y = *( float* )&i;
			y = y * ( 1.5f - ( half * y * y ) );
			y = y * ( 1.5f - ( half * y * y ) ); // 2nd iteration - better result
#ifdef PRECISE_FAST_SQRT
			y = y * ( 1.5f - ( half * y * y ) );
			y = y * ( 1.5f - ( half * y * y ) );
#endif
			return number * y;
#endif
		}

		FORCE_INLINE float InvSQRT( const float number )
		{
#ifndef FAST_SQRT
			return 1.0f / ( float )sqrt( number );
#else
			float half = 0.5f * number;
			int i = *( int* )&number;
			i = SQRT_MAGIC_CONSTANT - ( i >> 1 );
			float y = *( float* )&i;
			y = y * ( 1.5f - ( half * y * y ) );
			y = y * ( 1.5f - ( half * y * y ) ); // 2nd iteration - better result
#ifdef PRECISE_FAST_SQRT
			y = y * ( 1.5f - ( half * y * y ) );
			y = y * ( 1.5f - ( half * y * y ) );
#endif
			return y;
#endif
		}

	}
}

#endif // _SHARED_MATH_UTILITY_H_
